#!/usr/bin/env bash
# 项目初始化脚本 (Bash)
# 用于快速配置开发环境：安装依赖、配置 Git hooks、生成 .env 文件

# 错误处理设置
set -euo pipefail

# 退出码定义
readonly EXIT_SUCCESS=0
readonly EXIT_PREREQUISITES_MISSING=1
readonly EXIT_VERSION_MISMATCH=2
readonly EXIT_DEPENDENCY_FAILED=3
readonly EXIT_HOOKS_FAILED=4
readonly EXIT_CONFIG_FAILED=5

# 颜色定义（如果支持）
if [ -t 1 ]; then
    readonly RED='\033[0;31m'
    readonly GREEN='\033[0;32m'
    readonly YELLOW='\033[1;33m'
    readonly BLUE='\033[0;34m'
    readonly CYAN='\033[0;36m'
    readonly MAGENTA='\033[0;35m'
    readonly NC='\033[0m' # No Color
else
    readonly RED=''
    readonly GREEN=''
    readonly YELLOW=''
    readonly BLUE=''
    readonly CYAN=''
    readonly MAGENTA=''
    readonly NC=''
fi

# 颜色输出辅助函数
write_success() {
    echo -e "${GREEN}✅ $1${NC}"
}

write_info() {
    echo -e "${CYAN}📝 $1${NC}"
}

write_warning() {
    echo -e "${YELLOW}⚠️  $1${NC}"
}

write_failure() {
    echo -e "${RED}❌ $1${NC}"
}

write_step() {
    echo -e "${BLUE}$1${NC}"
}

# 路径规范化函数（确保使用 Unix 风格的正斜杠）
normalize_path() {
    local path="$1"
    # 将反斜杠转换为正斜杠（用于 Git Bash 兼容性）
    echo "$path" | sed 's|\\|/|g'
}

# 检测平台（用于跨平台兼容性处理）
detect_platform() {
    if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
        echo "Git Bash (Windows)"
    elif [[ "$OSTYPE" == "darwin"* ]]; then
        echo "macOS"
    elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
        echo "Linux"
    else
        echo "Unknown"
    fi
}

# 规范化环境变量中的路径（处理 Windows 风格路径）
normalize_env_paths() {
    # 在 Git Bash 环境中，某些环境变量可能包含 Windows 路径
    # 确保关键路径变量使用 Unix 风格
    if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
        # Git Bash 通常已经处理了路径转换，但我们确保一致性
        export PATH=$(echo "$PATH" | sed 's|\\|/|g')
    fi
}

# 检查初始化状态
check_init_status() {
    local env_exists=false
    local hooks_exist=false
    local lock_exists=false

    [ -f ".env" ] && env_exists=true
    [ -f ".git/hooks/pre-commit" ] && hooks_exist=true
    [ -f "uv.lock" ] && lock_exists=true

    if $env_exists && $hooks_exist && $lock_exists; then
        echo "INITIALIZED"
    elif $env_exists || $hooks_exist || $lock_exists; then
        echo "PARTIALLY_INITIALIZED"
    else
        echo "UNINITIALIZED"
    fi
}

# 检查命令是否存在
check_command() {
    local cmd=$1
    local install_url=$2

    if ! command -v "$cmd" &> /dev/null; then
        write_failure "未找到 $cmd 命令"
        if [ -n "$install_url" ]; then
            write_info "请访问: $install_url"
        fi
        return 1
    fi
    return 0
}

# 检查 Python 版本
check_python_version() {
    # 使用 UV 管理的 Python（兼容 Git Bash on Windows）
    local python_version
    python_version=$(uv run python --version 2>&1 | sed 's/Python //')

    local required_version="3.12"
    if ! printf '%s\n%s\n' "$required_version" "$python_version" | sort -V -C; then
        write_failure "需要 Python 3.12+，当前版本: $python_version"
        write_info ""
        write_info "请访问 https://www.python.org/downloads/ 升级 Python"
        write_info "或使用 pyenv 管理 Python 版本: https://github.com/pyenv/pyenv"
        exit $EXIT_VERSION_MISMATCH
    fi

    echo "  - Python: $python_version"
}

# 检查前置条件
check_prerequisites() {
    write_step "🔍 检查前置条件..."

    # 检查 Bash 版本
    if [ -n "$BASH_VERSION" ]; then
        local bash_major="${BASH_VERSION%%.*}"
        if [ "$bash_major" -lt 4 ]; then
            write_failure "需要 Bash 4.0 或更高版本，当前版本: $BASH_VERSION"
            write_info "请访问 https://www.gnu.org/software/bash/ 升级 Bash"
            write_info "macOS 用户可使用 Homebrew: brew install bash"
            exit $EXIT_VERSION_MISMATCH
        fi
        echo "  - Bash: $BASH_VERSION"
    fi

    # 检查 UV（必须在检查 Python 之前，因为使用 uv run python）
    if ! check_command "uv" ""; then
        write_info ""
        write_info "请访问以下链接安装 UV:"
        write_info "  https://docs.astral.sh/uv/getting-started/installation/"
        write_info ""
        write_info "快速安装命令 (macOS/Linux):"
        write_info "  curl -LsSf https://astral.sh/uv/install.sh | sh"
        exit $EXIT_PREREQUISITES_MISSING
    fi

    # 检查 Python 版本（通过 uv run，兼容各种环境）
    check_python_version

    local uv_version
    uv_version=$(uv --version 2>&1)
    echo "  - UV: $uv_version"

    # 检查 Git
    if ! check_command "git" ""; then
        write_warning "未检测到 Git（可选）"
        write_info "如需 Git hooks，请访问: https://git-scm.com/downloads"
    else
        local git_version
        git_version=$(git --version 2>&1)
        echo "  - Git: $git_version"
    fi

    write_success "环境检测通过"
}

# 安装项目依赖
install_dependencies() {
    write_step "📦 正在安装项目依赖..."

    if ! uv sync; then
        write_failure "依赖安装失败"
        write_info ""
        write_info "可能的原因:"
        write_info "  - 网络连接问题"
        write_info "  - pyproject.toml 配置错误"
        write_info "  - 磁盘空间不足"
        write_info ""
        write_info "建议操作:"
        write_info "  1. 检查网络连接"
        write_info "  2. 手动运行: uv sync --verbose"
        write_info "  3. 查看详细错误日志"
        exit $EXIT_DEPENDENCY_FAILED
    fi

    write_success "依赖安装完成！"
}

# 安装 Git hooks
install_git_hooks() {
    if [ ! -d ".git" ]; then
        write_warning "未检测到 Git 仓库，跳过 hooks 配置"
        return
    fi

    write_step "🪝 正在配置 Git hooks..."

    if ! uv run pre-commit install; then
        write_failure "Git hooks 安装失败"
        write_info ""
        write_info "建议操作:"
        write_info "  1. 检查 .git 目录权限"
        write_info "  2. 手动运行: uv run pre-commit install"
        exit $EXIT_HOOKS_FAILED
    fi

    write_success "Git hooks 配置完成！"
}

# 配置项目信息
configure_project_info() {
    local interactive="${1:-true}"

    write_step "📋 配置项目信息..."

    local project_name=""
    local project_description=""

    if [ "$interactive" = "true" ]; then
        # 读取当前配置
        local current_name="fastapi-demo"
        local current_desc="基于 FastAPI 的演示项目, 遵循最佳实践"

        if [ -f "pyproject.toml" ]; then
            current_name=$(grep -oP 'name\s*=\s*"\K[^"]+' pyproject.toml || echo "fastapi-demo")
            current_desc=$(grep -oP 'description\s*=\s*"\K[^"]+' pyproject.toml || echo "基于 FastAPI 的演示项目, 遵循最佳实践")
        fi

        echo ""
        echo "当前项目名称: $current_name"
        read -p "请输入新项目名称 (留空保持不变): " -r input_name
        if [ -n "$input_name" ]; then
            project_name="$input_name"
        else
            project_name="$current_name"
        fi

        echo "当前项目描述: $current_desc"
        read -p "请输入项目描述 (留空保持不变): " -r input_desc
        if [ -n "$input_desc" ]; then
            project_description="$input_desc"
        else
            project_description="$current_desc"
        fi
        echo ""
    else
        # 非交互模式，使用默认值
        project_name="fastapi-demo"
        project_description="基于 FastAPI 的演示项目, 遵循最佳实践"
    fi

    # 导出为全局变量
    export PROJECT_NAME="$project_name"
    export PROJECT_DESCRIPTION="$project_description"
}

# 更新 pyproject.toml
update_pyproject_toml() {
    local name="$1"
    local description="$2"

    write_step "📝 更新 pyproject.toml..."

    if [ ! -f "pyproject.toml" ]; then
        write_failure "pyproject.toml 文件不存在"
        exit $EXIT_CONFIG_FAILED
    fi

    # 使用 sed 替换项目名称和描述
    sed -i.bak -E "s/(name[[:space:]]*=[[:space:]]*\")[^\"]+/\1${name}/" pyproject.toml
    sed -i.bak -E "s/(description[[:space:]]*=[[:space:]]*\")[^\"]+/\1${description}/" pyproject.toml

    # 删除备份文件
    rm -f pyproject.toml.bak

    write_success "pyproject.toml 更新完成！"
}

# 更新 config.py
update_config_py() {
    local name="$1"
    local description="$2"

    write_step "📝 更新 app/core/config.py..."

    local config_path="app/core/config.py"

    if [ ! -f "$config_path" ]; then
        write_failure "$config_path 文件不存在"
        exit $EXIT_CONFIG_FAILED
    fi

    # 替换 APP_NAME 默认值
    sed -i.bak -E "s/(APP_NAME:[[:space:]]*Annotated\[[^]]+\][[:space:]]*=[[:space:]]*\")[^\"]+/\1${name}/" "$config_path"

    # 替换 APP_DESCRIPTION 默认值
    sed -i.bak -E "s/(APP_DESCRIPTION:[[:space:]]*Annotated\[[^]]+\][[:space:]]*=[[:space:]]*\")[^\"]+/\1${description}/" "$config_path"

    # 删除备份文件
    rm -f "${config_path}.bak"

    write_success "config.py 更新完成！"
}

# 更新 LICENSE
update_license() {
    local name="$1"

    write_step "📝 更新 LICENSE..."

    if [ ! -f "LICENSE" ]; then
        write_warning "LICENSE 文件不存在，跳过更新"
        return
    fi

    # 将项目名转换为合适的格式（首字母大写）
    local project_title
    project_title=$(echo "$name" | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2));}1' | sed 's/-/ /g')

    # 替换 LICENSE 中的项目名（匹配 "Copyright (c) YEAR Project Name" 格式）
    sed -i.bak -E "s/(Copyright \(c\) [0-9]{4} ).+/\1${project_title} Project/" LICENSE

    # 删除备份文件
    rm -f LICENSE.bak

    write_success "LICENSE 更新完成！"
}

# 生成配置文件
generate_config() {
    write_step "📝 正在生成配置文件..."

    # 检查 .env 是否已存在
    if [ -f ".env" ]; then
        read -p "检测到已存在 .env 文件。是否重新生成? (y/N): " -r response
        if [[ ! "$response" =~ ^[Yy]$ ]]; then
            write_info "⏭️  跳过 .env 生成"
            return
        fi

        # 备份现有文件
        local timestamp
        timestamp=$(date +%Y%m%d-%H%M%S)
        local backup_file=".env.backup.$timestamp"
        cp .env "$backup_file"
        write_info "📦 已备份现有配置到: $backup_file"

        # 清理旧备份（保留最近5个）
        # shellcheck disable=SC2012
        ls -t .env.backup.* 2>/dev/null | tail -n +6 | xargs rm -f 2>/dev/null || true
    fi

    # 生成新的 .env 文件
    if ! uv run -m scripts.generate_env --output .env --quiet; then
        write_failure "配置文件生成失败"
        write_info ""
        write_info "建议操作:"
        write_info "  1. 检查 scripts/generate_env.py 是否存在"
        write_info "  2. 检查文件系统权限"
        write_info "  3. 检查磁盘空间"
        exit $EXIT_CONFIG_FAILED
    fi

    write_success ".env 文件生成完成！"
}

# 生成 .env.example
generate_env_example() {
    write_step "📝 生成 .env.example..."

    if ! uv run -m scripts.generate_env --output .env.example --quiet; then
        write_failure ".env.example 生成失败"
        exit $EXIT_CONFIG_FAILED
    fi

    write_success ".env.example 生成完成！"
}

# 重建 Git 仓库
reset_git_repository() {
    write_step "🔄 重建 Git 仓库..."

    if [ -d ".git" ]; then
        read -p "是否重建 Git 仓库? 这将删除所有提交历史 (y/N): " -r response
        if [[ ! "$response" =~ ^[Yy]$ ]]; then
            write_info "⏭️  跳过 Git 仓库重建"
            return 1
        fi

        # 删除现有 .git 目录
        write_warning "正在删除现有 Git 仓库..."
        if ! rm -rf .git; then
            write_failure "无法删除 .git 目录"
            return 1
        fi
        write_info "已删除旧仓库"
    fi

    # 初始化新仓库
    if ! git init; then
        write_failure "Git 仓库初始化失败"
        return 1
    fi

    write_success "Git 仓库初始化完成！"
    return 0
}

# 主执行流程
main() {
    # 规范化环境变量路径（Git Bash 兼容性）
    normalize_env_paths

    echo ""
    echo -e "${MAGENTA}========================================${NC}"
    echo -e "${MAGENTA}🚀 FastAPI Demo 项目初始化${NC}"
    echo -e "${MAGENTA}========================================${NC}"
    local platform
    platform=$(detect_platform)
    echo -e "${CYAN}平台: $platform${NC}"
    echo ""

    # 检查初始化状态
    local status
    status=$(check_init_status)

    if [ "$status" = "INITIALIZED" ]; then
        write_info "✨ 项目已初始化，正在重新配置..."
    elif [ "$status" = "PARTIALLY_INITIALIZED" ]; then
        write_info "⚙️  检测到部分初始化，继续配置..."
    else
        write_info "🆕 开始首次初始化..."
    fi
    echo ""

    # 执行初始化步骤
    check_prerequisites

    # 配置项目信息
    configure_project_info true
    update_pyproject_toml "$PROJECT_NAME" "$PROJECT_DESCRIPTION"
    update_config_py "$PROJECT_NAME" "$PROJECT_DESCRIPTION"
    update_license "$PROJECT_NAME"

    install_dependencies

    # 重建 Git 仓库（可选）
    local git_rebuilt=false
    if reset_git_repository; then
        git_rebuilt=true
    fi

    # 如果重建了 Git 仓库或 Git 仓库存在，则安装 hooks
    if [ "$git_rebuilt" = true ] || [ -d ".git" ]; then
        install_git_hooks
    fi

    generate_config
    generate_env_example

    # 完成提示
    echo ""
    echo -e "${MAGENTA}========================================${NC}"
    echo -e "${GREEN}🎉 项目初始化完成！${NC}"
    echo -e "${MAGENTA}========================================${NC}"
    echo ""
    write_info "项目信息:"
    echo -e "${CYAN}  名称: $PROJECT_NAME${NC}"
    echo -e "${CYAN}  描述: $PROJECT_DESCRIPTION${NC}"
    echo ""
    write_info "可以运行以下命令开始开发:"
    echo -e "${CYAN}  make dev     # 启动开发服务器${NC}"
    echo -e "${CYAN}  make test    # 运行测试${NC}"
    echo ""

    exit $EXIT_SUCCESS
}

# 执行主函数
main "$@"
